<?php

namespace App\Services;

use App\Model\Normal;
use BsPaySdk\config\MerConfig;
use BsPaySdk\core\BsPay;
use BsPaySdk\core\BsPayClient;
use Util\Common;

class BspayService
{
    private $huifuId = '6666000175359347';


    public function __construct()
    {
        $this->initializeSdk();
    }

    /**
     * 初始化SDK
     */
    private function initializeSdk()
    {
        try {
            // 检查是否已经初始化
            if (!BsPay::getConfig()) {
                // 如果你有现成的配置文件，可以直接使用
                $configFile = BASE_PATH . '/config/bspay-config.json'; // 你的配置文件路径

                if (file_exists($configFile)) {
                    BsPay::init($configFile, false);
                } else {
                    // 如果没有配置文件，使用 MerConfig 中的配置创建一个
                    $this->createConfigFromFile();
                }

                // 更新商户ID
                $config = BsPay::getConfig();
                if ($config && !empty($config->huifu_id)) {
                    $this->huifuId = $config->huifu_id;
                }
            } else {
                // 使用现有配置中的商户ID
                $config = BsPay::getConfig();
                if ($config && !empty($config->huifu_id)) {
                    $this->huifuId = $config->huifu_id;
                }
            }
            Normal::logger('BSPay SDK 初始化成功'.json_encode($config), 'order-queue');
        } catch (\Exception $e) {
            throw new \Exception('BSPay SDK 初始化失败: ' . $e->getMessage());
        }
    }

    /**
     * 从 MerConfig 创建配置文件
     */
    private function createConfigFromFile()
    {
        // 获取 MerConfig 中的配置
        $merConfig = new \BsPaySdk\config\MerConfig();

        $configData = [
            'sys_id' => $merConfig->sys_id ?? '6666000175359347',
            'secret' => '', // MerConfig 中没有这个字段
            'huifu_id' => $merConfig->huifu_id ?? '6666000175359347',
            'product_id' => $merConfig->product_id,
            'rsa_merch_private_key' => $merConfig->rsa_merch_private_key ?? '',
            'rsa_huifu_public_key' => $merConfig->rsa_huifu_public_key ?? ''
        ];

        $tempDir = BASE_PATH . '/runtime';
        if (!is_dir($tempDir)) {
            mkdir($tempDir, 0755, true);
        }
        $configFile = $tempDir . '/bspay_config.json';
        file_put_contents($configFile, json_encode($configData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
        BsPay::init($configFile, false);
    }

    /**余额支付订单
     * @param $order
     * @return \BsPaySdk\core\BsPayRequestV2
     * @throws \Exception
     */
    public function createBalance($order){
        try{
            $request = new \BsPaySdk\request\V3TradePaymentJspayRequest();
            // 请求参数，不区分必填和可选，按照 api 文档 data 参数结构依次传入
            // 请求日期
            $request->setReqDate(date("Ymd"));
// 请求流水号
            $request->setReqSeqId($order->number);
// 商户号
            $request->setHuifuId($this->huifuId);
// 商品描述
            $request->setGoodsDesc('用户'.$order->user_id.'充值'.$order->fee);
// 交易类型
            $request->setTransAmt(number_format((float)$order->fee, 2, '.', ''));

            $extendInfoMap = [];
            switch($order->payment_type){
                case 1:
                    $request->setTradeType("T_MINIAPP");
                    $extendInfoMap['wx_data'] = $this->getWxData($order);
                    $extendInfoMap["notify_url"]= Common::MAIN_HOST.'/user/order/balance_notify';
                    break;
                case 2:
                    $request->setTradeType("A_JSAPI");
                    $extendInfoMap["alipay_data"] = $this->getAlipayData($order);
                    $extendInfoMap["notify_url"]= Common::MAIN_HOST.'/user/order/balance_notify';
                    break;
                default:
                    throw new \Exception('支付类型错误');
            }
            $request->setExtendInfo($extendInfoMap);
            # 创建请求Client对象，调用接口
            $client = new BsPayClient();
            $result = $client->postRequest($request);
            $response =[
                'response'=>$result->getRspDatas(),
                'error' =>$result->getErrorInfo(),
                'httpCode'=>$result->getHttpStateCode()
            ];
            return $response;
        }catch (\Exception $e){
            throw new \Exception($e->getMessage());
        }
    }


    /**创建支付订单
     * @param $order
     * @return \BsPaySdk\core\BsPayRequestV2
     * @throws \Exception
     */
    public function createPayment($order){
        try{
            $request = new \BsPaySdk\request\V3TradePaymentJspayRequest();
            // 请求参数，不区分必填和可选，按照 api 文档 data 参数结构依次传入
            // 请求日期
            $request->setReqDate(date("Ymd"));
// 请求流水号
            $request->setReqSeqId($order->number);
// 商户号
            $request->setHuifuId($this->huifuId);
// 商品描述
            $request->setGoodsDesc($order->sn.'-'.$order->channel_bumber.'付款'.$order->fee);
// 交易类型
            $request->setTransAmt(number_format((float)$order->fee, 2, '.', ''));

//            Normal::logger('order---fee'.$request->getTransAmt(),'order-queue');
            $extendInfoMap = [];
            switch($order->payment_type){
                case 1:
                    $request->setTradeType("T_MINIAPP");
                    $extendInfoMap['wx_data'] = $this->getWxData($order);
                    $extendInfoMap["notify_url"]= Common::MAIN_HOST.'/user/order/wx_notify';
                    break;
                case 2:
                    $request->setTradeType("A_JSAPI");
                    $extendInfoMap["alipay_data"] = $this->getAlipayData($order);
                    $extendInfoMap["notify_url"]= Common::MAIN_HOST.'/user/order/ali_notify';
                    break;
                default:
                    throw new \Exception('支付类型错误');
            }
            $request->setExtendInfo($extendInfoMap);
            # 创建请求Client对象，调用接口
            $client = new BsPayClient();
            $result = $client->postRequest($request);
            $response =[
               'response'=>$result->getRspDatas(),
               'error' =>$result->getErrorInfo(),
               'httpCode'=>$result->getHttpStateCode()
             ];
           return $response;
        }catch (\Exception $e){
            throw new \Exception($e->getMessage());
        }
    }

    public function getWxData($order){
        $dto["sub_appid"] = "wx3078f59712ad2197";
        $dto["sub_openid"] = $order->user->openid;
        return json_encode($dto,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    }

    public function getAlipayData($order){
        $dto['buyer_id'] =  $order->user->openid;
        return json_encode($dto,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    }

    /**退款申请
     * @param $order
     * @param $return_fee
     * @return \BsPaySdk\core\BsPayRequestV2
     * @throws \Exception
     */
    public function refund($refund,$notify=''){
        $request = new \BsPaySdk\request\V3TradePaymentScanpayRefundRequest();
// 请求日期
        $request->setReqDate(date("Ymd"));
// 请求流水号
        $request->setReqSeqId($refund->refund_no);
// 商户号
        $request->setHuifuId($this->huifuId);
// 申请退款金额
        $request->setOrdAmt($refund->reject_amt);
// 原交易请求日期
        $payAt = date('Ymd',strtotime($refund->pay_at));
        $request->setOrgReqDate($payAt);
        // 设置非必填字段
        $extendInfoMap = [];
        $extendInfoMap["org_req_seq_id"]= $refund->number;
        $extendInfoMap["notify_url"] = $notify;
        if(!$extendInfoMap["notify_url"]){
            $extendInfoMap["notify_url"]= Common::MAIN_HOST.'/user/order/refund_notify';
        }
        $request->setExtendInfo($extendInfoMap);
// 3. 发起API调用
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }


    public function createAccount($userInfo){
        $request = new \BsPaySdk\request\V2UserBasicdataIndvRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId(rand(10,99).$userInfo['mobile_no'].time());
        $request->setName($userInfo['name']);
        $request->setCertType($userInfo['cert_type']);
        $request->setCertNo($userInfo['cert_no']);
        $request->setMobileNo($userInfo['mobile_no']);
        $request->setCertValidityType($userInfo['cert_validity_type']);
        $request->setCertBeginDate($userInfo['cert_begin_date']);
        $extendInfoMap = [];
       $extendInfoMap["cert_end_date"]= $userInfo['cert_end_date'];
       $request->setExtendInfo($extendInfoMap);
// 3. 发起API调用
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }

    public function createBusiness($business){
        $request = new \BsPaySdk\request\V2UserBasicdataEntRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId($business->id.time().rand(1000,9999));
        $request->setRegName($business->reg_name);
        $request->setLicenseCode($business->license_code);
        $request->setLicenseValidityType($business->license_validity_type);
        $request->setLicenseBeginDate($business->license_begin_date);
        $request->setLicenseEndDate($business->license_end_date);
        $request->setRegProvId($business->reg_prov_id);
        $request->setRegAreaId($business->reg_area_id);
        $request->setRegDistrictId($business->reg_district_id);
        $request->setRegDetail($business->reg_detail);
        $request->setLegalName($business->legal_name);
        $request->setLegalCertType($business->legal_cert_type);
        $request->setLegalCertNo($business->legal_cert_no);
        $request->setLegalCertValidityType($business->legal_cert_validity_type);
        $request->setLegalCertBeginDate($business->legal_cert_begin_date);
        $request->setLegalCertEndDate($business->legal_cert_end_date);
        $request->setContactName($business->contact_name);
        $request->setContactMobile($business->contact_mobile);
        $extendInfoMap = [];
        $extendInfoMap["file_list"]= [
            ["file_type"=>"F02","file_id"=>$business->card_front_id],
            ["file_type"=>"F03","file_id"=>$business->card_back_id],
            ["file_type"=>"F08","file_id"=>$business->bank_img_id],
            ["file_type"=>"F07","file_id"=>$business->license_img_id]
        ];
        $extendInfoMap["file_list"] = json_encode($extendInfoMap["file_list"],JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
        $request->setExtendInfo($extendInfoMap);
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response = [
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }


    public function createBankAccount($userInfo){
        $request = new \BsPaySdk\request\V2UserBusiOpenRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId($userInfo->id.time().rand(1000,9999));
        $request->setHuifuId($userInfo->third_account_id);
        $request->setUpperHuifuId($this->huifuId);
        $cardInfo = [];
        $cardInfo['card_type'] = '1';
        $cardInfo['card_no'] = $userInfo->withdraw_account_bank_card_no;
        $cardInfo['card_name'] = $userInfo->withdraw_account_bank_card_username;
        $cardInfo['cert_type'] = "00";
        $cardInfo['cert_no'] = $userInfo->cert_id;
        $cardInfo['cert_validity_type'] = $userInfo->cert_validity_type;
        $cardInfo['cert_begin_date'] = $userInfo->cert_begin_date;
        $cardInfo['cert_end_date'] = $userInfo->cert_end_date;
        $cardInfo['prov_id'] = $userInfo->prov_id;
        $cardInfo['area_id'] = $userInfo->area_id;
        $extendInfoMap = [];
        $cashConfig= [];
        $cashConfig['cash_type'] = 'DM';
        $cashConfig['fix_amt']='0.00';
        $cashConfig['fee_rate']='0.00';
        $cashConfig['out_fee_flag'] = '2';
        $cashConfig['out_fee_huifu_id'] = $userInfo->third_account_id;
        $extendInfoMap["cash_config"]= json_encode([$cashConfig]);
        $extendInfoMap["card_info"]= json_encode($cardInfo);
        $request->setExtendInfo($extendInfoMap);
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }

    public function createBusinessAccount($userInfo){
        $request = new \BsPaySdk\request\V2UserBusiOpenRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId($userInfo->id.time().rand(1000,9999));
        $request->setHuifuId($userInfo->third_account_id);
        $request->setUpperHuifuId($this->huifuId);
        $cardInfo = [];
        $cardInfo['card_type'] = '0';
        $cardInfo['card_no'] = $userInfo->business->card_no;
        $cardInfo['card_name'] = $userInfo->business->card_name;
        $cardInfo['cert_type'] = "00";
        $cardInfo['cert_no'] = $userInfo->business->legal_cert_no;
        $cardInfo['cert_validity_type'] = $userInfo->business->legal_cert_validity_type;
        $cardInfo['cert_begin_date'] = $userInfo->business->legal_cert_begin_date;
        $cardInfo['cert_end_date'] = $userInfo->business->legal_cert_end_date;
        $cardInfo['prov_id'] = $userInfo->prov_id;
        $cardInfo['area_id'] = $userInfo->area_id;
        $cardInfo['branch_code'] = $userInfo->business->branch_code;
        $extendInfoMap = [];
        $cashConfig= [];
        $cashConfig['cash_type'] = 'DM';
        $cashConfig['fix_amt']='0.00';
        $cashConfig['fee_rate']='0.00';
        $cashConfig['out_fee_flag'] = '2';
        $cashConfig['out_fee_huifu_id'] = $userInfo->third_account_id;
        $extendInfoMap["cash_config"]= json_encode([$cashConfig]);
        $extendInfoMap["card_info"]= json_encode($cardInfo);
        $request->setExtendInfo($extendInfoMap);
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }



    public function balancePay($params){
        $request = new \BsPaySdk\request\V2TradeAcctpaymentPayRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId($params['order_no']);
        $request->setOutHuifuId($this->huifuId);
        $request->setOrdAmt($params['money']);
        $request->setAcctSplitBunch(json_encode($params['acct_split_bunch']));
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }


    public function balanceRefund($params){
        $request = new \BsPaySdk\request\V2TradeAcctpaymentRefundRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId($params['refund_no']);
        $request->setHuifuId($this->huifuId);
        $request->setOrdAmt($params['money']);
        $request->setOrgReqDate($params['balance_date']);
        $request->setOrgHfSeqId($params['balance_hf_id']);
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }

    public function drawCash($params){
        $request = new \BsPaySdk\request\V2TradeSettlementEncashmentRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId($params['order_no']);
        $request->setHuifuId($params['third_account_id']);
        $request->setIntoAcctDateType('DM');
        $request->setTokenNo($params['token_no']);
        $request->setCashAmt($params['money']);
        $extendInfoMap = [];
        $extendInfoMap["notify_url"]= Common::MAIN_HOST.'/distributors/cash_notify';
        $request->setExtendInfo($extendInfoMap);
        $client = new BsPayClient();
        $result = $client->postRequest($request);
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }


    /**上传图片
     * @param $params
     * @return array
     * @throws \Exception
     */
    public function uploadFile($params){
        $request = new \BsPaySdk\request\V2SupplementaryPictureRequest();
        $request->setReqDate(date("Ymd"));
        $request->setReqSeqId(time().rand(1000,9999));
        $request->setFileType($params['type']);
        $extendInfoMap = [];
        $extendInfoMap['huifu_id'] = $this->huifuId;
        $request->setExtendInfo($extendInfoMap);
        $client = new BsPayClient();
        $result = $client->postRequest($request,new \CURLFile(BASE_PATH . '/public/upload/id_card.jpg'));
        $response =[
            'response'=>$result->getRspDatas(),
            'error' =>$result->getErrorInfo(),
            'httpCode'=>$result->getHttpStateCode()
        ];
        return $response;
    }

    public function uploadLocalFile($params){
        $url = 'https://api.huifu.com/v2/supplementary/picture';
        $dataParams = [
            'file_type' => $params['type'],
            'huifu_id' => $this->huifuId,
            'req_date' => date("Ymd"),
            'req_seq_id' => time().rand(1000,9999)
        ];

        $postData = [
            'sys_id' => '6666000175359347',  // 系统ID
            'product_id' => 'PAYUN',         // 产品ID
            'data' => json_encode($dataParams, JSON_UNESCAPED_UNICODE),
            'file' => new \CURLFile($params['file_path'])
        ];
        return $this->httpPost($url, $postData);
    }


    public function httpPost($uri,$data)
    {
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $uri,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => $data,
        ));
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);
        if ($error) {
            throw new \Exception('cURL Error: ' . $error);
        }
        return [
            'response' => json_decode($response, true),
            'httpCode' => $httpCode
        ];
    }



}
